import SysConfig from '@/models/system/sys-config.model';
import { Op } from 'sequelize';
import { getLogger } from '@/utils/logger';
import { ConfigQueryParams, ConfigFormData } from '@/types/system/config';
import cacheUtils from '@/utils/cache/cache.util';

const logger = getLogger("sys-config-service", {
  console: false,
});
const consoleLogger = getLogger("sys-config-service");

// sys_config 缓存 key 前缀
const SYS_CONFIG_PREFIX = 'sys_config:';

/**
 * 生成 sys_config 缓存 key
 */
function getSysConfigCacheKey(configKey: string): string {
  return `${SYS_CONFIG_PREFIX}${configKey}`;
}

/**
 * 设置 sys_config 缓存
 */
async function setSysConfigCache(configKey: string, configValue: string): Promise<void> {
  try {
    const cacheResult = await cacheUtils.set(getSysConfigCacheKey(configKey), configValue);
    if (cacheResult.success) {
      logger.debug(`[sys_config] 设置缓存: ${configKey}=${configValue}`);
    } else {
      consoleLogger.error(`[sys_config] 设置缓存失败: ${configKey}, ${cacheResult.error?.message || cacheResult.error || '未知错误'}`);
    }
  } catch (error) {
    consoleLogger.error(`[sys_config] 设置缓存异常: ${error instanceof Error ? error.message : String(error)}`);
  }
}

/**
 * 获取 sys_config 缓存
 */
async function getSysConfigCache(configKey: string): Promise<string | null> {
  try {
    const cacheResult = await cacheUtils.get(getSysConfigCacheKey(configKey));
    if (cacheResult.success && cacheResult.data) {
      logger.debug(`[sys_config] 获取缓存: ${configKey}=${cacheResult.data}`);
      return cacheResult.data;
    } else if (!cacheResult.success) {
      consoleLogger.error(`[sys_config] 获取缓存失败: ${configKey}, ${cacheResult.error?.message || cacheResult.error || '未知错误'}`);
    }
    return null;
  } catch (error) {
    consoleLogger.error(`[sys_config] 获取缓存异常: ${error instanceof Error ? error.message : String(error)}`);
    return null;
  }
}

/**
 * 删除 sys_config 缓存
 */
async function delSysConfigCache(configKey: string): Promise<void> {
  try {
    const cacheResult = await cacheUtils.del(getSysConfigCacheKey(configKey));
    if (cacheResult.success) {
      logger.debug(`[sys_config] 删除缓存: ${configKey}`);
    } else {
      consoleLogger.error(`[sys_config] 删除缓存失败: ${configKey}, ${cacheResult.error?.message || cacheResult.error || '未知错误'}`);
    }
  } catch (error) {
    consoleLogger.error(`[sys_config] 删除缓存异常: ${error instanceof Error ? error.message : String(error)}`);
  }
}

/**
 * 获取所有 sys_config 缓存 key
 */
async function getAllSysConfigCacheKeys(): Promise<string[]> {
  try {
    const pattern = `${SYS_CONFIG_PREFIX}*`;
    const cacheResult = await cacheUtils.keys(pattern);
    if (cacheResult.success && cacheResult.data) {
      logger.debug(`[sys_config] 获取所有缓存键, 数量=${cacheResult.data.length}`);
      return cacheResult.data;
    } else if (!cacheResult.success) {
      consoleLogger.error(`[sys_config] 获取所有缓存键失败: ${cacheResult.error?.message || cacheResult.error || '未知错误'}`);
    }
    return [];
  } catch (error) {
    consoleLogger.error(`[sys_config] 获取所有缓存键异常: ${error instanceof Error ? error.message : String(error)}`);
    return [];
  }
}

/**
 * 全量加载 sys_config 参数到缓存
 */
export async function loadAllSysConfigToCache(): Promise<void> {
  try {
    // 使用consoleLogger记录操作开始
    consoleLogger.info('全量加载系统参数到缓存');
    
    const allConfigs = await SysConfig.findAll();
    logger.info(`查询到系统参数总数: ${allConfigs.length}`);
    
    for (const config of allConfigs) {
      if (config.configKey && config.configValue !== undefined) {
        await setSysConfigCache(config.configKey, config.configValue);
      }
    }
    
    // 记录操作结果
    consoleLogger.info(`已全量加载系统参数到缓存，总数: ${allConfigs.length}`);
  } catch (error) {
    consoleLogger.error(`全量加载系统参数到缓存失败: ${error instanceof Error ? error.message : String(error)}`);
  }
}

/**
 * 参数设置服务层
 * 提供参数配置的增删改查、唯一性校验、缓存刷新等功能
 */
class SysConfigService {
  /**
   * 分页查询参数配置列表
   * @param params 查询参数
   */
  async getConfigList(params: ConfigQueryParams) {
    try {
      const { pageNum = 1, pageSize = 10, configName, configKey, configType, beginTime, endTime } = params;
       // 使用consoleLogger记录操作开始
      consoleLogger.info(`查询参数配置列表: pageNum=${pageNum}, pageSize=${pageSize}, configName=${configName}, configKey=${configKey}, configType=${configType}, beginTime=${beginTime}, endTime=${endTime}`);
      const where: any = {};
      if (configName) where.configName = { [Op.like]: `%${configName}%` };
      if (configKey) where.configKey = { [Op.like]: `%${configKey}%` };
      if (configType) where.configType = configType;
      if (beginTime && endTime) {
        where.createTime = { [Op.between]: [beginTime, endTime] };
      }
      const parsedPageNum = typeof pageNum === 'string' ? parseInt(pageNum, 10) : pageNum;
      const parsedPageSize = typeof pageSize === 'string' ? parseInt(pageSize, 10) : pageSize;
      const { count, rows } = await SysConfig.findAndCountAll({
        where,
        offset: (parsedPageNum - 1) * parsedPageSize,
        limit: parsedPageSize,
        order: [['createTime', 'DESC']]
      });
      logger.info(`参数配置列表查询: 总数=${count}, 页码=${parsedPageNum}, 每页=${parsedPageSize}`);
      return {
        total: count,
        rows,
        pageNum: parsedPageNum,
        pageSize: parsedPageSize
      };
    } catch (error) {
      consoleLogger.error(`查询参数配置列表失败: ${error instanceof Error ? error.message : String(error)}`);
      throw new Error('查询参数配置列表失败');
    }
  }

  /**
   * 根据ID获取参数配置
   * @param configId 参数主键
   */
  async getConfigById(configId: number) {
    try {
      // 使用consoleLogger记录操作开始
      consoleLogger.info(`根据ID查询参数配置: configId=${configId}`);
      
      // 检查configId是否有效
      if (isNaN(configId)) {
        consoleLogger.error(`根据ID查询参数配置失败: configId "${configId}" 不是有效的数字`);
        throw new Error('无效的参数配置ID');
      }
      
      const config = await SysConfig.findByPk(configId);
      
      if (config) {
        logger.info(`参数配置查询成功: configId=${configId}, configKey=${config.configKey}`);
      } else {
        logger.info(`未找到参数配置: configId=${configId}`);
      }
      
      return config;
    } catch (error) {
      consoleLogger.error(`根据ID查询参数配置失败: ${error instanceof Error ? error.message : String(error)}`);
      throw new Error('查询参数配置失败');
    }
  }

  /**
   * 根据参数键名获取参数值
   * @param configKey 参数键名
   */
  async getConfigValueByKey(configKey: string) {
    try {
      // 使用consoleLogger记录操作开始
      consoleLogger.info(`根据键名查询参数值: configKey=${configKey}`);
      
      // 检查参数
      if (!configKey) {
        consoleLogger.error('根据键名查询参数值失败: 参数键名不能为空');
        throw new Error('参数键名不能为空');
      }
      
      // 优先查 Redis
      const cacheValue = await getSysConfigCache(configKey);
      if (cacheValue !== null) {
        logger.info(`参数值命中缓存: configKey=${configKey}`);
        return cacheValue;
      }
      
      // Redis 无则查库
      logger.debug(`参数值未命中缓存，从数据库查询: configKey=${configKey}`);
      const config = await SysConfig.findOne({ where: { configKey } });
      
      if (config && config.configValue !== undefined) {
        // 查库后写入缓存
        await setSysConfigCache(configKey, config.configValue);
        logger.info(`参数值查询成功并已写入缓存: configKey=${configKey}`);
        return config.configValue;
      }
      
      logger.info(`未找到参数值: configKey=${configKey}`);
      return null;
    } catch (error) {
      consoleLogger.error(`根据参数键名查询参数值失败: ${error instanceof Error ? error.message : String(error)}`);
      throw new Error('查询参数值失败');
    }
  }

  /**
   * 新增参数配置
   * @param data 参数数据
   */
  async createConfig(data: ConfigFormData) {
    try {
      // 使用consoleLogger记录操作开始
      consoleLogger.info(`新增参数配置: configName=${data.configName}, configKey=${data.configKey}`);
      
      // 检查必要参数
      if (!data.configKey || !data.configName) {
        consoleLogger.error('新增参数配置失败: 参数名称或键名不能为空');
        throw new Error('参数名称和键名不能为空');
      }
      
      const result = await SysConfig.create(data);
      
      // 新增成功后写入缓存
      if (data.configKey && data.configValue !== undefined) {
        logger.debug(`新增参数配置写入缓存: configKey=${data.configKey}`);
        await setSysConfigCache(data.configKey, data.configValue);
      }
      
      // 记录操作结果
      logger.info(`参数配置新增成功: configId=${result.configId}, configKey=${result.configKey}`);
      
      return result;
    } catch (error) {
      consoleLogger.error(`新增参数配置失败: ${error instanceof Error ? error.message : String(error)}`);
      throw new Error('新增参数配置失败');
    }
  }

  /**
   * 修改参数配置
   * @param configId 参数主键
   * @param data 参数数据
   */
  async updateConfig(configId: number, data: ConfigFormData) {
    try {
      // 使用consoleLogger记录操作开始
      consoleLogger.info(`修改参数配置: configId=${configId}, configName=${data.configName}, configKey=${data.configKey}`);
      
      // 检查configId是否有效
      if (isNaN(configId)) {
        consoleLogger.error(`修改参数配置失败: configId "${configId}" 不是有效的数字`);
        throw new Error('无效的参数配置ID');
      }
      
      // 检查必要参数
      if (!data.configKey || !data.configName) {
        consoleLogger.error('修改参数配置失败: 参数名称或键名不能为空');
        throw new Error('参数名称和键名不能为空');
      }
      
      // 查询旧参数
      const oldConfig = await SysConfig.findByPk(configId);
      if (!oldConfig) {
        logger.warn(`修改的参数配置不存在: configId=${configId}`);
        return [0]; // 返回0表示没有记录被更新
      }
      
      // 执行更新
      const result = await SysConfig.update(data, { where: { configId } });
      
      // 如果 key 变更，删除旧缓存
      if (oldConfig && oldConfig.configKey !== data.configKey) {
        logger.info(`参数键名已变更: ${oldConfig.configKey} -> ${data.configKey}, 删除旧缓存`);
        await delSysConfigCache(oldConfig.configKey!);
      }
      
      // 更新缓存
      if (data.configKey && data.configValue !== undefined) {
        logger.debug(`更新参数配置缓存: configKey=${data.configKey}`);
        await setSysConfigCache(data.configKey, data.configValue);
      }
      
      // 记录操作结果
      logger.info(`参数配置修改完成: configId=${configId}, 影响行数=${result[0]}`);
      
      return result;
    } catch (error) {
      consoleLogger.error(`修改参数配置失败: ${error instanceof Error ? error.message : String(error)}`);
      throw new Error('修改参数配置失败');
    }
  }

  /**
   * 删除参数配置
   * @param configIds 参数主键数组
   */
  async deleteConfig(configIds: number[]) {
    try {
      // 使用consoleLogger记录操作开始
      consoleLogger.info(`删除参数配置: configIds=${JSON.stringify(configIds)}`);
      
      // 检查参数
      if (!configIds || configIds.length === 0) {
        consoleLogger.error('删除参数配置失败: 参数ID不能为空');
        throw new Error('参数ID不能为空');
      }
      
      // 查询所有待删除参数
      const configs = await SysConfig.findAll({ where: { configId: { [Op.in]: configIds } } });
      
      if (configs.length === 0) {
        logger.warn(`未找到要删除的参数配置: configIds=${JSON.stringify(configIds)}`);
        throw new Error('未找到要删除的参数配置');
      }
      
      // 执行删除
      const result = await SysConfig.destroy({ where: { configId: { [Op.in]: configIds } } });
      
      // 删除缓存
      for (const config of configs) {
        if (config.configKey) {
          logger.debug(`删除参数配置缓存: configKey=${config.configKey}`);
          await delSysConfigCache(config.configKey);
        }
      }
      
      // 记录操作结果
      logger.info(`参数配置删除完成: 删除项数量=${configIds.length}, 影响行数=${result}`);
      
      return result;
    } catch (error) {
      consoleLogger.error(`删除参数配置失败: ${error instanceof Error ? error.message : String(error)}`);
      throw new Error('删除参数配置失败');
    }
  }

  /**
   * 校验参数键名唯一性
   * @param configKey 参数键名
   * @param configId 可选，排除自身
   */
  async checkConfigKeyUnique(configKey: string, configId?: number) {
    try {
      // 使用consoleLogger记录操作开始
      consoleLogger.info(`校验参数键名唯一性: configKey=${configKey}, configId=${configId || '未提供'}`);
      
      // 检查参数
      if (!configKey) {
        logger.warn('校验参数键名唯一性: 参数键名为空');
        return false;
      }
      
      const where: any = { configKey };
      if (configId) where.configId = { [Op.ne]: configId };
      
      const count = await SysConfig.count({ where });
      const isUnique = count === 0;
      
      // 记录结果
      logger.info(`参数键名唯一性校验完成: configKey=${configKey}, 是否唯一=${isUnique}`);
      
      return isUnique;
    } catch (error) {
      consoleLogger.error(`校验参数键名唯一性失败: ${error instanceof Error ? error.message : String(error)}`);
      // 发生错误时，返回false以确保安全
      return false;
    }
  }

  /**
   * 刷新参数缓存（清空所有 sys_config:xxx 缓存并重新加载）
   */
  async refreshCache() {
    try {
      // 使用consoleLogger记录操作开始
      consoleLogger.info('刷新参数缓存');
      
      // 获取所有 sys_config:xxx 缓存 key
      const keys = await getAllSysConfigCacheKeys();
      logger.info(`获取到参数缓存键: 数量=${keys.length}`);
      
      // 清除现有缓存
      if (keys.length > 0) {
        logger.debug('清除现有参数缓存');
        await cacheUtils.del(keys);
      }
      
      // 重新加载
      await loadAllSysConfigToCache();
      
      // 记录操作结果
      consoleLogger.info('参数缓存刷新成功');
      
      return true;
    } catch (error) {
      consoleLogger.error(`参数缓存刷新失败: ${error instanceof Error ? error.message : String(error)}`);
      throw new Error('参数缓存刷新失败');
    }
  }
}

export default new SysConfigService(); 